package com.yz.fanrenmianshi.blackfilter;

import cn.hutool.bloomfilter.BitMapBloomFilter;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

@Slf4j
public class BlackIpUtils {

    private static BitMapBloomFilter bloomFilter;
    private static final String LOCAL_CACHE_FILE = "blackip-cache.yaml";
    private static final String FALLBACK_CONFIG_FILE = "blackip-fallback.yaml";
    // 检查服务是否可用
    @Getter
    private static volatile boolean serviceAvailable = true;

    // 判断 ip 是否在黑名单内
    public static boolean isBlackIp(String ip) {
        if (bloomFilter == null) {
            log.warn("布隆过滤器未初始化，使用降级策略");
            initFallbackBloomFilter();
        }
        return bloomFilter != null && bloomFilter.contains(ip);
    }

    // 重建 ip 黑名单（增加异常处理和降级）
    public static void rebuildBlackIp(String configInfo) {
        try {
            rebuildBlackIpInternal(configInfo);
            // 成功时保存到本地缓存
            saveToLocalCache(configInfo);
            serviceAvailable = true;
            log.info("黑名单重建成功");
        } catch (Exception e) {
            log.error("重建黑名单失败，尝试降级策略", e);
            serviceAvailable = false;
            fallbackStrategy();
        }
    }
    
    private static void rebuildBlackIpInternal(String configInfo) {
        if (StrUtil.isBlank(configInfo)) {
            configInfo = "{}";
        }
        
        Yaml yaml = new Yaml();
        Map map = yaml.loadAs(configInfo, Map.class);
        List<String> blackIpList = (List<String>) map.get("blackIpList");
        
        synchronized (BlackIpUtils.class) {
            if (CollectionUtil.isNotEmpty(blackIpList)) {
                BitMapBloomFilter bitMapBloomFilter = new BitMapBloomFilter(958506);
                for (String ip : blackIpList) {
                    bitMapBloomFilter.add(ip);
                }
                bloomFilter = bitMapBloomFilter;
                log.info("黑名单重建成功，包含 {} 个IP", blackIpList.size());
            } else {
                bloomFilter = new BitMapBloomFilter(100);
                log.info("黑名单为空，初始化空过滤器");
            }
        }
    }
    
    // 降级策略
    private static void fallbackStrategy() {
        log.info("执行降级策略");
        
        // 1. 尝试从本地缓存恢复
        if (loadFromLocalCache()) {
            log.info("从本地缓存恢复黑名单成功");
            return;
        }
        
        // 2. 使用预设的降级配置
        if (loadFallbackConfig()) {
            log.info("使用降级配置恢复黑名单成功");
            return;
        }
        
        // 3. 最后的保底策略：初始化空过滤器
        initEmptyBloomFilter();
        log.warn("所有降级策略失败，使用空黑名单过滤器");
    }
    
    // 从本地缓存加载
    private static boolean loadFromLocalCache() {
        try {
            File cacheFile = new File(LOCAL_CACHE_FILE);
            if (cacheFile.exists()) {
                String cachedConfig = FileUtil.readUtf8String(cacheFile);
                rebuildBlackIpInternal(cachedConfig);
                log.info("从本地缓存文件加载黑名单成功");
                return true;
            }
        } catch (Exception e) {
            log.error("从本地缓存加载失败", e);
        }
        return false;
    }
    
    // 加载降级配置
    private static boolean loadFallbackConfig() {
        try {
            InputStream inputStream = BlackIpUtils.class.getClassLoader()
                .getResourceAsStream(FALLBACK_CONFIG_FILE);
            if (inputStream != null) {
                try {
                    String fallbackConfig = new String(IoUtil.readBytes(inputStream), "UTF-8");
                    rebuildBlackIpInternal(fallbackConfig);
                    log.info("从降级配置文件加载黑名单成功");
                    return true;
                } finally {
                    IoUtil.close(inputStream);
                }
            }
        } catch (Exception e) {
            log.error("加载降级配置失败", e);
        }
        return false;
    }
    
    // 初始化空过滤器
    private static void initEmptyBloomFilter() {
        synchronized (BlackIpUtils.class) {
            bloomFilter = new BitMapBloomFilter(100);
            log.info("初始化空布隆过滤器");
        }
    }
    
    // 初始化降级过滤器
    private static void initFallbackBloomFilter() {
        if (bloomFilter == null) {
            fallbackStrategy();
        }
    }
    
    // 保存到本地缓存
    private static void saveToLocalCache(String configInfo) {
        try {
            if (StrUtil.isNotBlank(configInfo) && !"{}" .equals(configInfo)) {
                FileUtil.writeUtf8String(configInfo, LOCAL_CACHE_FILE);
                log.debug("黑名单配置已保存到本地缓存");
            }
        } catch (Exception e) {
            log.error("保存本地缓存失败", e);
        }
    }
}
